TalentSync

AI resume builder and ATS optimizer for job seekers. Tailored resumes, outreach, and interview prep from one profile.

Context providers

The context providers architecture and state synchronization mechanisms in the frontend application.

Repository layout#

The provider stack is established at the root of the Next.js app shell and composed around the application’s layout. Providers wrap the entire app subtree, enabling session-aware routing, centralized query caching, and cross-component notifications.

Building blocks#

  • Providers: QueryClient plus the FastAPI SessionProvider from session-provider.tsx, then React Query devtools.
  • LayoutContent: Wraps the main content area with a SidebarProvider to manage collapsible sidebar state and composes the Navbar and main content region.
  • use-toast: A toast notification service with a reducer-driven state machine and a lightweight pub/sub mechanism to broadcast toast updates across the app.

Key provider responsibilities:

  • SessionProvider: Provides authentication state and session-related utilities to the app.
  • QueryClientProvider: Exposes React Query’s cache and background refresh capabilities to all components.
  • SidebarProvider: Manages a shared layout state (collapsed/collapsed) for responsive navigation.

How it fits together#

The provider architecture establishes a layered context stack that enables:

  • Authentication context via session-provider.tsx
  • Global query cache via React Query
  • Cross-component notifications via a local toast store
  • Layout state via a custom SidebarProvider

Provider hierarchy and composition#

  • RootLayout composes Providers and LayoutContent, so all pages inherit the same context stack.
  • Providers initializes a singleton QueryClient :
  • Stale time configured to treat data as fresh for a short period.
  • Retry attempts for transient failures.
  • Window focus refetch disabled to reduce unnecessary network activity.
  • SessionProvider hydrates from getSession() and keeps /api/v1/auth/me in sync.
  • LayoutContent composes SidebarProvider to share layout state across the main content area.

React query integration and state propagation#

React Query is used pervasively for data fetching, caching, and state updates. Hooks encapsulate query keys, fetchers, and optimistic updates. Mutations commonly invalidate related queries to keep the UI synchronized.

Context creation and isolation#

  • Authentication context: useSession() from session-provider.tsx. Do not import next-auth/react.
  • Query cache context: Provided by QueryClientProvider. All queries share a single cache instance with a shared stale/retry policy.
  • Toast context: Provided by a local reducer store exposed via use-toast. This is isolated to the app boundary and does not leak into server-side rendering contexts.
  • Layout context: Provided by SidebarProvider inside LayoutContent. This isolates sidebar state to the main content area.

Habits that help:

  • Keep provider order consistent across the app to avoid subtle hydration mismatches.
  • Prefer wrapping only the necessary subtree with custom providers to minimize re-renders.

State sharing patterns#

  • Shared UI state: SidebarProvider shares collapsed state across components in the main layout.
  • Cross-component notifications: use-toast maintains a single source of truth for toast messages and broadcasts updates to all subscribers.
  • Data state: React Query manages normalized cache entries keyed by query keys. Mutations invalidate related keys to propagate changes.

Patterns:

  • Use query keys to scope cache invalidation precisely.
  • Combine multiple small providers for focused state domains (e.g., layout vs. data vs. UI feedback).

Integration with database connections and encryption utilities#

  • Database connection: Prisma client is initialized globally and reused across the backend. While not directly part of frontend providers, it underpins the APIs consumed by frontend services.
  • Encryption utilities: Encryption helpers are provided for sensitive data handling. They rely on environment variables for keys and throw explicit errors when keys are missing.

Guidelines:

  • Ensure environment variables are present in production to avoid runtime failures.
  • Use encryption utilities for sensitive payloads before sending to the backend.

Dependencies#

The provider stack introduces dependencies between components and services. Hooks depend on services, which in turn call backend endpoints. Mutations depend on React Query’s cache invalidation to synchronize state.

Performance#

  • Caching strategy: Configure staleTime to balance freshness and network usage. Short-lived caches reduce bandwidth but increase requests; longer caches improve performance but risk staleness.
  • Retries: Limit retries to avoid thundering herds on backend failures. Use exponential backoff at the service level if needed.
  • Refetch policies: Disable refetchOnWindowFocus to prevent unnecessary background refetches during idle browsing.
  • Selective re-renders: Use shallow equality checks and split providers to limit the scope of re-renders. Keep heavy providers near the root only when necessary.
  • Devtools: Keep devtools closed in production to avoid overhead.

[No sources needed since this section provides general guidance]

Troubleshooting#

Common issues and remedies:

  • Hydration mismatch: Ensure Providers wrap the entire app subtree consistently. Avoid toggling providers conditionally based on SSR state.
  • Toast not appearing: Verify use-toast is imported and called within the Providers boundary. Confirm that the Toaster component is rendered.
  • Query not updating after mutation: Ensure mutations call invalidateQueries with the correct queryKey. Check that the service returns a successful response.
  • Encryption errors: Confirm ENCRYPTION_KEY is set in the environment. The encryption module throws when the key is missing.
  • Sidebar state not persisting: Confirm SidebarProvider is placed at the top of the layout subtree and that child components consume useSidebar correctly.

Debugging tips:

  • Use React Query devtools to inspect cache state, query status, and invalidation triggers.
  • Temporarily enable devtools in development to observe query lifecycles.
  • Add logging around mutations to verify invalidation keys and error handling paths.